#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <nlohmann/json.hpp>
#include <vector>
#include <algorithm>

using namespace std;
using json = nlohmann::json;

class KVClient {
private:
    string _server_ip;
    int _server_port;
    
    bool connectAndSend(const string& command, string& response) {
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) {
            return false;
        }
        
        // 设置连接和接收超时
        struct timeval timeout;
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;
        setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
        
        struct sockaddr_in server_addr;
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(_server_port);
        server_addr.sin_addr.s_addr = inet_addr(_server_ip.c_str());
        
        if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
            close(sockfd);
            return false;
        }
        
        // 发送命令（确保以换行符结束）
        string command_with_newline = command + "\n";
        ssize_t sent = send(sockfd, command_with_newline.c_str(), command_with_newline.length(), 0);
        if (sent < 0) {
            close(sockfd);
            return false;
        }
        
        // 接收响应
        char buffer[8192];
        ssize_t total_received = 0;
        bool received_complete = false;
        
        while (total_received < sizeof(buffer) - 1) {
            ssize_t received = recv(sockfd, buffer + total_received, sizeof(buffer) - total_received - 1, 0);
            if (received <= 0) {
                break;
            }
            total_received += received;
            
            // 检查是否收到完整响应（以换行符或缓冲区满结束）
            if (total_received > 0) {
                buffer[total_received] = '\0';
                // 检查是否有换行符表示响应结束
                for (ssize_t i = total_received - 1; i >= 0; i--) {
                    if (buffer[i] == '\n') {
                        received_complete = true;
                        buffer[i] = '\0'; // 移除换行符
                        break;
                    }
                }
                if (received_complete) break;
            }
        }
        
        close(sockfd);
        
        if (total_received > 0) {
            response = string(buffer);
            return true;
        }
        
        return false;
    }

    void printColored(const string& text, const string& color_code) {
        cout << color_code << text << "\033[0m";
    }

    // 解析带引号的参数
    vector<string> parseCommand(const string& command) {
        vector<string> tokens;
        string token;
        bool in_quotes = false;
        
        for (char c : command) {
            if (c == '"') {
                in_quotes = !in_quotes;
            } else if (isspace(c) && !in_quotes) {
                if (!token.empty()) {
                    tokens.push_back(token);
                    token.clear();
                }
            } else {
                token += c;
            }
        }
        
        if (!token.empty()) {
            tokens.push_back(token);
        }
        
        return tokens;
    }

public:
    KVClient(const string& ip = "127.0.0.1", int port = 8082) 
        : _server_ip(ip), _server_port(port) {}
    
    string sendCommand(const string& command) {
        string response;
        if (connectAndSend(command, response)) {
            return response;
        }
        return R"({"成功":false,"错误信息":"连接服务器失败"})";
    }
    
    void printResult(const string& response) {
        try {
            json j = json::parse(response);
            bool success = j.value("成功", false);
            string data = j.value("数据", "");
            string error_msg = j.value("错误信息", "");
            int code = j.value("状态码", 0);
            
            cout << "\n";
            if (success) {
                printColored("✓ 操作成功", "\033[32m");
            } else {
                printColored("✗ 操作失败", "\033[31m");
            }
            cout << " (状态码: " << code << ")" << endl;
            
            if (!error_msg.empty()) {
                printColored("信息: " + error_msg + "\n", "\033[33m");
            }
            
            if (!data.empty()) {
                printColored("返回数据:\n", "\033[36m");
                // 尝试解析数据为JSON
                try {
                    if (data.front() == '[' || data.front() == '{') {
                        json data_json = json::parse(data);
                        cout << data_json.dump(2) << endl;
                    } else {
                        cout << data << endl;
                    }
                } catch (...) {
                    cout << data << endl;
                }
            }
            
            cout << "---" << endl;
        } catch (const exception& e) {
            cout << "响应解析错误: " << response << endl;
        }
    }
    
    void showWelcome() {
        cout << "\033[36m" << R"(
    ╔══════════════════════════════════════╗
    ║          银行分布式系统客户端        ║
    ║        Bank Distributed System       ║
    ╚══════════════════════════════════════╝
        )" << "\033[0m" << endl;
        cout << "服务器: " << _server_ip << ":" << _server_port << endl;
        cout << "输入 'HELP' 查看可用命令，'quit' 退出" << endl << endl;
    }
    
    void showHelp() {
        cout << "\033[33m" << "可用命令:" << "\033[0m" << endl;
        cout << "  \033[32m用户管理:\033[0m" << endl;
        cout << "    REGISTER_USER <用户名> \"<姓名>\" <身份证号> <手机号> [邮箱]" << endl;
        cout << "    GET_USER <用户ID>" << endl;
        cout << "  \033[32m账户管理:\033[0m" << endl;
        cout << "    CREATE_ACCOUNT <用户ID> <账户类型> [初始存款]" << endl;
        cout << "    GET_BALANCE <账户号>" << endl;
        cout << "    GET_ACCOUNT_DETAILS <账户号>" << endl;
        cout << "    GET_USER_ACCOUNTS <用户ID>" << endl;
        cout << "  \033[32m交易功能:\033[0m" << endl;
        cout << "    DEPOSIT <账户号> <金额> [描述]" << endl;
        cout << "    WITHDRAW <账户号> <金额> [描述]" << endl;
        cout << "    TRANSFER <转出账户> <转入账户> <金额> [描述]" << endl;
        cout << "    GET_TRANSACTIONS <账户号> [限制条数]" << endl;
        cout << "  \033[32m统计功能:\033[0m" << endl;
        cout << "    GET_STATS" << endl;
        cout << "  \033[32m会话管理:\033[0m" << endl;
        cout << "    CREATE_SESSION <用户ID>" << endl;
        cout << "    GET_SESSION <会话ID>" << endl;
        cout << "  \033[32m系统命令:\033[0m" << endl;
        cout << "    PING, HELP, CLEAR, CLUSTER_STATUS" << endl;
        cout << endl;
        cout << "注意: 包含空格的参数请使用双引号，例如: \"张三\"" << endl;
        cout << endl;
    }
    
    void interactiveMode() {
        showWelcome();
        
        string command;
        vector<string> commandHistory;
        size_t historyIndex = 0;
        
        while (true) {
            cout << "银行系统> ";
            getline(cin, command);
            
            if (command.empty()) continue;
            
            if (command == "quit" || command == "exit") {
                break;
            }
            
            if (command == "clear") {
                #ifdef _WIN32
                    system("cls");
                #else
                    system("clear");
                #endif
                showWelcome();
                continue;
            }
            
            if (command == "HELP" || command == "help") {
                showHelp();
                continue;
            }
            
            if (command == "history") {
                cout << "命令历史:" << endl;
                for (size_t i = 0; i < commandHistory.size(); ++i) {
                    cout << "  " << i + 1 << ": " << commandHistory[i] << endl;
                }
                continue;
            }
            
            // 添加到历史（限制最近20条）
            commandHistory.push_back(command);
            if (commandHistory.size() > 20) {
                commandHistory.erase(commandHistory.begin());
            }
            
            printResult(sendCommand(command));
        }
        
        cout << "感谢使用银行系统，再见！" << endl;
    }
    
    void singleCommandMode(const string& command) {
        printResult(sendCommand(command));
    }
};

int main(int argc, char* argv[]) {
    string server_ip = "127.0.0.1";
    int server_port = 8082;
    bool cluster_mode = false;
    
    // 解析命令行参数
    for (int i = 1; i < argc; i++) {
        string arg = argv[i];
        if (arg == "--cluster" || arg == "-c") {
            cluster_mode = true;
        } else if (arg.find(".") != string::npos) {
            server_ip = arg;
        } else if (arg.find(":") != string::npos) {
            // 格式: 127.0.0.1:8082
            size_t pos = arg.find(":");
            server_ip = arg.substr(0, pos);
            server_port = stoi(arg.substr(pos + 1));
        } else if (i == 1 && arg.find(".") == string::npos && arg.find(":") == string::npos) {
            try {
                server_port = stoi(arg);
            } catch (...) {
                cerr << "无效的端口: " << arg << endl;
                return 1;
            }
        }
    }
    
    if (cluster_mode) {
        // 尝试多个可能的集群端口
        vector<int> cluster_ports = {8082, 8083, 8084};
        bool connected = false;
        
        for (int port : cluster_ports) {
            cout << "尝试连接集群节点端口 " << port << "..." << endl;
            KVClient test_client(server_ip, port);
            string response = test_client.sendCommand("PING");
            
            // 更宽松的成功判断
            if (!response.empty() && response.find("PONG") != string::npos) {
                cout << "✓ 连接到集群节点端口: " << port << endl;
                server_port = port;
                connected = true;
                break;
            } else if (!response.empty()) {
                // 即使不是PONG，只要有响应也算连接成功
                cout << "✓ 连接到集群节点端口: " << port << " (响应: " << response.substr(0, 50) << "...)" << endl;
                server_port = port;
                connected = true;
                break;
            } else {
                cout << "✗ 端口 " << port << " 连接失败" << endl;
            }
        }
        
        if (!connected) {
            cerr << "无法连接到任何集群节点" << endl;
            return 1;
        }
    }
    
    KVClient client(server_ip, server_port);
    
    if (argc == 1|| cluster_mode) {
        // 交互模式
        client.interactiveMode();
    } else {
        // 单命令模式
        string command;
        for (int i = 1; i < argc; i++) {
            string arg = argv[i];
            if (arg != "--cluster" && arg != "-c") {
                if (!command.empty()) command += " ";
                command += arg;
            }
        }
        client.singleCommandMode(command);
    }
    
    return 0;
}
